/**
 * This file is released under the GNU General Public License.
 * Refer to the COPYING file distributed with this package.
 *
 * Copyright (c) 2008-2009 WURFL-Pro srl
 */
package net.sourceforge.wurfl.core.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import net.sourceforge.wurfl.core.Constants;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.text.StrBuilder;

/**
 * User-Agent helper class. 
 * 
 * <p>
 * This class have several utility methods to support the user-agent matching.
 * </p>
 * 
 * @author WURFL-PRO SRL, Rome, Italy
 * @version $Id: UserAgentUtils.java 1045 2009-03-09 15:52:53Z filippo.deluca $
 */
public final class UserAgentUtils {

	/** Compiled pattern to strip out quotes in UAProfile */
	public static final Pattern stripQuotePattern = Pattern.compile("\"");

	/** Compiled pattern to parse UAProfile namespace */
	public static final Pattern nameSpacePattern = Pattern.compile("ns=(\\d*)");

	/**
	 * This method parse the Http request to find the user-agent string. It
	 * search first the <code>UA</code> request parameter and then across
	 * <code>x-device-user-agent</code> and <code>User-Agent</code> header
	 * value.
	 * 
	 * @param request
	 *            The <code>HttpServletRequest</code> to parse. It must be not
	 *            null value.
	 * @return The user-agent string reported by the Http request.
	 */
	public static String getUserAgent(HttpServletRequest request) {

		Validate.notNull(request, "The HttpServletRequest is null");

		String userAgent = "";
		if (request.getParameter("UA") != null) {
			userAgent = "" + request.getParameter("UA");
		} else if (request.getHeader("x-device-user-agent") != null) {
			userAgent = "" + request.getHeader("x-device-user-agent");
		} else {
			userAgent = "" + request.getHeader("User-Agent");
		}

		return userAgent;
	}

	/**
	 * This method parse the HTTP request to obtain the UAProf URL.
	 * 
	 * <p>
	 * It search across the <code>x-wap-profile</code>,<code>Profile</code>
	 * and <code>wap-profile</code> to find the UAProf URL. If this headers
	 * returns a null value it try to obtain right header to read, parsing the
	 * <code>Opt</code> header.
	 * </p>
	 * 
	 * @param request
	 *            The <code>HttpServletRequest</code> parsed to obtain UAProf,
	 *            it must be not null.
	 * @return a String containing the UAProf URL.
	 */
	public static String getUaProfile(HttpServletRequest request) {

		Validate.notNull(request, "The HttpServletRequest is null");

		String headerName = null;
		String uaProfile = null;

		if (request.getHeader("x-wap-profile") != null) {
			headerName = "x-wap-profile";
		} else if (request.getHeader("Profile") != null) {
			headerName = "Profile";
		} else if (request.getHeader("wap-profile") != null) {
			headerName = "wap-profile";
		} else if (request.getHeader("Opt") != null) {
			String optHeader = request.getHeader("Opt");
			String namespaceNumber = null;

			if (optHeader != null && optHeader.indexOf("ns=") != -1) {

				Matcher matcher = nameSpacePattern.matcher(optHeader);

				try {
					namespaceNumber = matcher.group(1);

					// Using not sync StrBuilder
					StrBuilder sb = new StrBuilder(namespaceNumber);
					sb.append("-Profile");

					headerName = sb.toString();
				} catch (Exception e) {
					headerName = null;
				}

			}
		}

		if (headerName != null && headerName.trim().length() > 0) {
			uaProfile = request.getHeader(headerName);
		}

		// Strip out quotes from uaProfile
		if (uaProfile != null && uaProfile.trim().length() > 0) {
			stripQuotePattern.matcher(uaProfile).replaceAll("");
		}

		return uaProfile;
	}

	/**
	 * This method return true if HTTP request is came from a Xhtml enable
	 * device.
	 * <p>
	 * It parse the <code>accept</code> header to find some keyword, that
	 * demonstrate the device support Xhtml content.
	 * </p>
	 * 
	 * @param httpRequest
	 *            The <code>HttpServletRequest</code> from target device, it
	 *            must be not null.
	 * @return true, if the requester device support Xhtml content, false
	 *         otherwise.
	 */
	public static boolean isXhtmlRequester(HttpServletRequest httpRequest) {

		Validate.notNull(httpRequest, "HttpRequest is null");
		
		String acceptHeader = httpRequest.getHeader("accept");

		if (acceptHeader != null
				&& ((acceptHeader.indexOf(
						Constants.ACCEPT_HEADER_VND_WAP_XHTML_XML) != -1)
						|| (acceptHeader.indexOf(
								Constants.ACCEPT_HEADER_XHTML_XML) != -1) || (acceptHeader.indexOf(
								Constants.ACCEPT_HEADER_TEXT_HTML) != -1))) {
			return true;
		}

		return false;
	}

	/**
	 * Return if the given user-agent is mobile also seem to be web-browser.
	 * 
	 * @param userAgent
	 * @return True if the given user-agent is mobile device, false otherwise.
	 */
	public static boolean isMobileBrowser(String userAgent) {
		
		Validate.notNull(userAgent, "userAgent is null");

		if (org.apache.commons.lang.StringUtils.contains(userAgent, "Tablet")) {
			return true;
		}
		
		return false;
	}
	
}
